package com.njlime.core.helper.dic;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.njlime.core.utils.DateUtil;
import com.njlime.core.utils.StringUtil;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.file.*;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Observable;

/**
 * 指定目录文件变化监控类
 *
 * @author cancer
 */
public class WatchFilePathTask extends Observable implements Runnable {
    private Logger log = Logger.getLogger(WatchFilePathTask.class);

    private static final String filePath = WatchFilePathTask.class.getClassLoader().getResource("").getPath();

    private WatchService watchService;

    // 此方法一经调用，立马可以通知观察者，在本例中是监听线程
    public void doBusiness() {
        if (true) {
            super.setChanged();
        }
        //通知观察者，重启线程
        notifyObservers();
    }

    @Override
    public void run() {
        try {
            //获取监控服务
            watchService = FileSystems.getDefault().newWatchService();
            log.debug("获取监控服务" + watchService);
            Path path = new File(filePath).toPath();
            log.debug("@@@:Path:" + path);

            //启动时检查是否有未解析的符合要求的文件
            reloadDic();

            //注册监控服务，监控新增事件
            WatchKey key = path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
            while (true) {
                key = watchService.take();
                for (WatchEvent<?> event : key.pollEvents()) {

                    //获取目录下修改的文件名
                    String fileName = event.context().toString();

                    //检查文件名是否符合要求
                    if ("dictionaryHelper.xml".equals(fileName)) {
                        log.info(DateUtil.dataFormat(new Date()) + "数据字典被修改");

                        //启动线程更新数据字典
                        log.debug("更新数据字典");
                        reloadDic();
                    }
                }
                key.reset();
            }
        } catch(Exception e) {
            e.printStackTrace();
            log.info("发生错误，重启线程");
            doBusiness();//在抛出异常时调用，通知观察者，让其重启线程
        }
    }

    private void reloadDic() throws Exception{
        //读取js文件
        String jsFile = this.getClass().getResource("/").getPath().replace("WEB-INF","").replace("classes","") + "static" + File.separator + "api" + File.separator + "param.js";
        OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(jsFile), "utf-8");
        StringBuffer jsBuffer = new StringBuffer();
        jsBuffer.append("var $sysParam = {\r\n");
        //读取数据字典
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(this.getClass().getClassLoader().getResource("dictionaryHelper.xml"));
        List list = document.selectNodes("//group");
        Iterator iter = list.iterator();
        while (iter.hasNext()) {
            Node node = (Node) iter.next();
            if (node instanceof Element) {
                Element element = (Element) node;
                String groupName = element.attributeValue("name");
                String groupClass = element.attributeValue("class");
                Class clazz = null;
                if(!StringUtil.isEmpty(groupClass)){
                    clazz = Class.forName(groupClass);
                }
                // 取组内数据字典项
                Iterator eleIter = element.elementIterator();
                JSONArray jsonArray = new JSONArray();
                while (eleIter.hasNext()) {
                    Element elem = (Element) eleIter.next();
                    String display = elem.attributeValue("display");
                    String value = elem.attributeValue("value");
                    if(clazz != null){
                        DictionaryHelper.getInstance().putDic(groupName,display,clazz.getField(value).get(null));
                    }else{
                        DictionaryHelper.getInstance().putDic(groupName,display,value);
                    }
                    //写入js文件
                    JSONObject jsonObject = new JSONObject();
                    if(clazz != null){
                        jsonObject.put("id",clazz.getField(value).get(null));
                    }else{
                        jsonObject.put("id",value);
                    }
                    jsonObject.put("name",display);
                    jsonArray.add(jsonObject);
                }
                jsBuffer.append(groupName + ":" + jsonArray.toJSONString() + ",\r\n");
            }
        }
        jsBuffer.append("getName:function(a, b) {\r\n");
        jsBuffer.append("return function(a) {\r\n");
        jsBuffer.append("for (var c = 0; $.isArray(a) && c < a.length; c++) if (a[c].id == b) return a[c].name;\r\n");
        jsBuffer.append("return \"function\" == typeof a ? a(b) :\"\";\r\n");
        jsBuffer.append("}(this[a]);\r\n");
        jsBuffer.append("}\r\n");
        jsBuffer.append("};\r\n");
        out.write(jsBuffer.toString());
        out.flush();
        try{
            out.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}
